﻿/////////////////////////////////////////////////////////////////////
//
//	Map_FVG C# Class Library.
//
//	GPS
//	lettura file *.gpx creato dal GPS
//
//	autore: Gustavo Mainardi 
//	versione: 1.0
//	data: 01/12/2015
//
//
//	Cronologia delle versioni:
//
//	Versione 1.0 01/01/2015
//		versione originale
//
//////////////////////////////////////////////////////////////////////////
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Schema;
using System.IO;
using System.Globalization;
using System.Data.SQLite;

namespace Map_Fvg
{
    public partial class GPS : Form
    {
        public struct GPSpoint
        {
            public double lat;
            public double lon;
            public double ele;
            public string time; 
            public int easting;
            public int northing;
            public int gb_X;
            public int gb_Y;
        }

        public static GPSpoint[] vectG = new GPSpoint[1];
        public static int nPoints;
        public static int option;

        public GPS()
        {


            InitializeComponent();

/*
            textBox1.Text = "UTMtoGB.txt";
            MessageBox.Show("opzione non ancora operante");
            
           return;
            */

            ElencoFiles.InitialDirectory = FormIniz.cartellaGPS;
            ElencoFiles dlg = new ElencoFiles();
            if (dlg.ShowDialog() != DialogResult.OK)
            {
                option = 0;
                return;
            }

            string ssF = ElencoFiles.sezioneFound;

            string path = FormIniz.cartellaGPS + "gps.xsd";

            XmlSchemaSet sc = new XmlSchemaSet();

            // Add the schema to the collection.
            sc.Add(null, path);

            XmlReaderSettings readerSettings = new XmlReaderSettings();
            readerSettings.Schemas = sc;
            if(option == 1 || option == 2) readerSettings.ValidationType = ValidationType.Schema;
            if (option == 3 || option == 4) readerSettings.ValidationType = ValidationType.None;
            readerSettings.ValidationEventHandler += new ValidationEventHandler(readerSettingsValidationEventHandler);

            XmlReader reader = XmlReader.Create(ssF, readerSettings);

            int elem = 0;
            string time1 = string.Empty;
       //     string time2 = "bounds ";  // string.Empty;
            string bounds = string.Empty;
            string name = string.Empty;
            string desc = string.Empty;
            string desc1 = string.Empty;

            while (reader.Read())
            {
                    switch (reader.NodeType)
                    {
                        case XmlNodeType.Element:
                            elem = 0;
                            if (reader.Name.Equals("<gpx")) elem = 1;
                            if (reader.Name.Equals("time")) elem = 2;
                            if (reader.Name.Equals("bounds")) elem = 3;
                            if (reader.Name.Equals("name")) elem = 4;
                            if (reader.Name.Equals("desc")) elem = 5;
                            if (reader.Name.Equals("trkseg")) goto L20;

                            break;
                        case XmlNodeType.Text:
                            if (elem == 4)
                                {
                                    name = reader.Value;
                                }
                            if (elem == 5)
                            {
                                desc = reader.Value;
                            }
                            break;
                        case XmlNodeType.CDATA:
                            desc1 = reader.Value;
                            break;
                        case XmlNodeType.ProcessingInstruction:
                            //                MessageBox.Show("<?{0} {1}?>" + reader.Name + "  " + reader.Value);
                            break;
                        case XmlNodeType.Comment:
       //                     MessageBox.Show("<!--{0}-->" + reader.Value);
                            break;
                        case XmlNodeType.XmlDeclaration:
                            //                  MessageBox.Show("<?xml version='1.0'?>");
                            break;
                        case XmlNodeType.Document:
                            break;
                        case XmlNodeType.DocumentType:
                            //                  MessageBox.Show("<!DOCTYPE {0} [{1}]" + reader.Name + "  " + reader.Value);
                            break;
                        case XmlNodeType.EntityReference:
                            //                MessageBox.Show(reader.Name);
                            break;
                        case XmlNodeType.EndElement:
                            //                   MessageBox.Show("</{0}>" + reader.Name);
                            break;
                    }
                }

            
        L20:
           
    
            int ipos = desc.IndexOf("Points");

            if (ipos == -1)
            {
                /*
                MessageBox.Show("errore 2 ");
                this.Close();
                return;
                */
                nPoints = 10000;
                goto L35;

            }

            ipos += 8;
            int len = desc.Length;
            string ss = desc.Substring(ipos,len-ipos);

            ss = ss.Trim();

            ipos = ss.IndexOf(' ');
    //        MessageBox.Show(ipos.ToString() + " :" + ss);

            len = ss.Length;
            
            string points = ss.Substring(0,ipos);
            nPoints = int.Parse(points);
 
            L35:
            string mess1 = "\n\n\nsi vuole continuare nell'analisi?"; 
            string mess2 = "\n\n\nsi vuole inserire il tracciato nella mappa?"; 
            string caption = string.Concat("descrizione file ",ssF) ;
            if(desc.Equals(string.Empty)) desc = desc1;
            if (option == 1 || option == 3) desc = string.Concat(desc, mess1);
            if (option == 2 || option == 4) desc = string.Concat(desc, mess2);
 
            var result = MessageBox.Show(desc, caption,
                                 MessageBoxButtons.YesNo,
                                 MessageBoxIcon.Question);
            if (result == DialogResult.No) return;

            if (nPoints <= 0)
            {
                MessageBox.Show("numero anomalo di punti ");
                return;
            }

            vectG = new GPSpoint[nPoints];
            NumberFormatInfo nfi = new CultureInfo("en-US", false).NumberFormat;
            nfi.NumberDecimalDigits = 6;

            int ipt = -1;
            while (reader.Read())
            {
                switch (reader.NodeType)
                {
                    case XmlNodeType.Element:
  //                      MessageBox.Show("<{0}>" + reader.Name);
                    if (reader.Name.Equals("trkpt")) 
                        {
                            elem = 1;
                            ++ipt;
                            break;
                        }
                        if (reader.Name.Equals("ele")) 
                        {
                            elem = 2;
                            break;
                        }
                        if (reader.Name.Equals("time")) 
                        {
                            elem = 3;
                            break;
                        }
                        break;
                    case XmlNodeType.Text:
                        if(elem == 2)
                        {
                            string s2 = reader.Value;
                            vectG[ipt].ele = double.Parse(s2,nfi);
                            break;
                        }
                        if(elem == 3)
                        {
                            vectG[ipt].time = reader.Value;
                            break;
                        }
                        MessageBox.Show(reader.Value);
                      break;
            case XmlNodeType.CDATA:
                //               MessageBox.Show("<![CDATA[{0}]]>" + reader.Value);
                break;
            case XmlNodeType.ProcessingInstruction:
                //                MessageBox.Show("<?{0} {1}?>" + reader.Name + "  " + reader.Value);
                break;
            case XmlNodeType.Comment:
                MessageBox.Show("<!--{0}-->" + reader.Value);
                break;
            case XmlNodeType.XmlDeclaration:
                //                  MessageBox.Show("<?xml version='1.0'?>");
                break;
            case XmlNodeType.Document:
                break;
            case XmlNodeType.DocumentType:
                //                  MessageBox.Show("<!DOCTYPE {0} [{1}]" + reader.Name + "  " + reader.Value);
                break;
            case XmlNodeType.EntityReference:
                //                MessageBox.Show(reader.Name);
                break;
            case XmlNodeType.EndElement:
                //                   MessageBox.Show("</{0}>" + reader.Name);
                break;
        }

        if (reader.HasAttributes)
        {
            //               MessageBox.Show("Attributes of <" + reader.Name + ">");
            while (reader.MoveToNextAttribute())
            {
                if (reader.Name.Equals("lat"))
                {
                    string s2 = reader.Value;
                    vectG[ipt].lat = double.Parse(s2, nfi);
                } 
                if (reader.Name.Equals("lon"))
                {
                    string s2 = reader.Value;
                    vectG[ipt].lon = double.Parse(s2, nfi);
                } 

//                MessageBox.Show(" {0}={1} " + reader.Name + "  " + reader.Value);
            }
            // Move the reader back to the element node.
            reader.MoveToElement();
        }

    }
            nPoints = ipt + 1;
 //           MessageBox.Show("OK   " + nPoints.ToString());

            UTM conv = new UTM();
            conv.geoToUTM();

            int iret = readFileQU5000();
            if (iret != 0) return;
 
            int ipt1 = 0;
            int rept = 0;
            int maxRept = 18;
            bool brept = false;

            string mess = string.Empty;

            if (option == 2 || option == 4) goto L40;
            
L30:        ss = string.Empty;              //  verifica
            option = 0;

            int utmX = GPS.vectG[ipt1].gb_X;
            int utmY = GPS.vectG[ipt1].gb_Y;

            int elem1 = findFirstElement(utmX, utmY);

            for(ipt = ipt1+1;ipt < nPoints;++ipt)
            {
                utmX = GPS.vectG[ipt].gb_X;
                utmY = GPS.vectG[ipt].gb_Y;

                int ifound = pointInTheElement(utmX, utmY);
                if(ifound == 0) break;
            }
            int npt = ipt - ipt1;
            if (rept < maxRept)
            {
                ss = string.Concat(codex + "  numero punti  : ", npt.ToString(), " / ", nPoints.ToString());
                //            MessageBox.Show(codex + "  numero punti  : " + npt.ToString() + " - " + ipt.ToString() + " / " + nPoints.ToString());
                mess = string.Concat(mess,ss,"\n\n");
           }
            if (rept > maxRept && brept == false)
            {
                mess = string.Concat(mess + "  . . . . .");
                brept = true;
            }
            ++rept;
            ipt1 = ipt; 
            if (ipt1 < nPoints) goto L30;

            MessageBox.Show(mess);
            return;

        L40: ;      //      inserimento
            ss = string.Empty; 
            option = 0;
            string nameElement = FormIniz.nameElement;

            if (nameElement == null)
            {
                MessageBox.Show("selezionare l'elemento in cui inserire il tracciato GPS");
                return;
            }
            int pntSimb = -1;
            string stcl = "5L002SE";
            for (int i = 0; i < ViewQ.nSimb; ++i)
            {
                    if (ViewQ.vectS[i].codice.Contains(stcl)) 
                    {
                     pntSimb = i;   
                     break;   
                    }
            }
            if (pntSimb == -1)
            {
                string ss2 = string.Empty;

                using (SQLiteConnection conn = SetConnection())
                {
                    conn.Open();
                    using (SQLiteCommand cmd = new SQLiteCommand(conn))
                    {
                        cmd.CommandText = "select * from linea where codice_stclasse = '" + stcl + "'";
                        SQLiteDataReader reader1 = cmd.ExecuteReader();
                        if (reader1.HasRows)
                        {
                            while (reader1.Read())
                            {
                                pntSimb = ViewQ.nSimb;
                                ViewQ.vectS[pntSimb].codice = reader1.GetString(0).ToString();
                                ss2 = reader1.GetString(1).ToString();
                                ViewQ.vectS[pntSimb].denom = reader1.GetString(2).ToString();
                                string ss1 = reader1.GetString(3).ToString();
                                ViewQ.vectS[pntSimb].penType = int.Parse(ss1);
                                ViewQ.vectS[pntSimb].tratto = reader1.GetString(4).ToString();
                                string[] words;
                                char[] delimiterChars = { ' ', ',' };
                                ss1 = reader1.GetString(5).ToString();

                                words = ss1.Split(delimiterChars);
                                byte b1 = byte.Parse(words[0]);
                                byte b2 = byte.Parse(words[1]);
                                byte b3 = byte.Parse(words[2]);
                                byte b4 = byte.Parse(words[3]);
                                ViewQ.vectS[pntSimb].icolor = Color.FromArgb(b1, b2, b3, b4);

                                ViewQ.vectS[pntSimb].visib = 1;
                                ViewQ.vectS[pntSimb].selected = 1;

                                ViewQ.nSimb += 1;
                            }
                        }
                        else
                        {
                            MessageBox.Show("non si trovano le proprietà per la linea " + stcl);
                            return;

                        }
                    }

                    conn.Close();
                }

                using (SQLiteConnection conn = SetConnection())
                {
                    conn.Open();
                    using (SQLiteCommand cmd = new SQLiteCommand(conn))
                    {
                        cmd.CommandText = "select * from classi";

                        SQLiteDataReader reader2 = cmd.ExecuteReader();
                        if (reader2.HasRows)
                        {
                            while (reader2.Read())
                            {
                                if (ss2.Contains(reader2.GetString(0).ToString()))
                                {
                                    ViewQ.vectS[pntSimb].classe = reader2.GetString(1).ToString();
                                    break;
                                }
                            }
                        }
                    }
                    conn.Close();
                }
            }

            int irept = 0;
        L50: utmX = GPS.vectG[ipt1].gb_X;
            utmY = GPS.vectG[ipt1].gb_Y;

            elem1 = findFirstElement(utmX, utmY);
            if (elem1 < 0) return;

            if (nameElement.Contains(codex)) ++irept;
            for (ipt = ipt1 + 1; ipt < nPoints; ++ipt)
            {
                utmX = GPS.vectG[ipt].gb_X;
                utmY = GPS.vectG[ipt].gb_Y;

                int ifound = pointInTheElement(utmX, utmY);
                if (ifound == 0) break;
            }
            npt = ipt - ipt1;
            if (!nameElement.Contains(codex)) npt = 0;
            if (rept < maxRept)
            {
                ss = string.Concat(codex + "  numero punti  : ", npt.ToString(), " / ", nPoints.ToString());
                //            MessageBox.Show(codex + "  numero punti  : " + npt.ToString() + " - " + ipt.ToString() + " / " + nPoints.ToString());
                mess = string.Concat(mess, ss, "\n\n");

            }
            if (rept > maxRept && brept == false)
            {
                mess = string.Concat(mess + "  . . . . .");
                brept = true;
            }
            ++rept;

            if (npt > 0)
            {
                int isel = ViewQ.nShapes;
                ViewQ.vectShapes[isel].nVertices = npt;
                ViewQ.vectShapes[isel].pntSimb = pntSimb;
                int ipnt = ViewQ.vectShapes[isel - 1].pntpL;
                int nVertices = ViewQ.vectShapes[isel - 1].nVertices;
                ipnt += nVertices;
                ViewQ.vectShapes[isel].pntpL = ipnt;
 //               ++ipt1;
                for (int i = 0; i < npt; ++i)
                {
                    ViewQ.PL[ipnt + i].X = GPS.vectG[ipt1 + i].gb_X;
                    ViewQ.PL[ipnt + i].Y = GPS.vectG[ipt1 + i].gb_Y;
                }


                ViewQ.vectShapes[isel].modifica = 3;
                ViewQ.vectShapes[isel].edizione = "3";
                ViewQ.vectShapesPointAB(isel);
                ViewQ.vectShapesQuota(isel);
                ViewQ.vectShapesLunghezza(isel);
                Save.modificaLinea = 1;
                ViewQ.nShapes += 1;

                int numID = ViewQ.vectShapes[isel - 1].numID;
                ViewQ.vectShapes[isel].numID = numID + 1;
            }
                 
            ipt1 = ipt;
            if (ipt1 < nPoints) goto L50;

            if (irept == 0)
            {
                MessageBox.Show("l'elemento  " + nameElement + " non contiene il tracciato GPS");
                return;
            }
            else
            {
                MessageBox.Show(mess);
                ViewQ.ActiveForm.Refresh();
            }
        }



        static void readerSettingsValidationEventHandler(object sender, ValidationEventArgs e)
    {
        if (e.Severity == XmlSeverityType.Warning)
        {
            MessageBox.Show("WARNING: " + e.Message);
            Console.WriteLine(e.Message);
        }
        else if (e.Severity == XmlSeverityType.Error)
        {
            MessageBox.Show("ERROR: " + e.Message);
            
        }
    }


        private SQLiteConnection SetConnection()
        {
            string DataSource = "Data Source=";
            DataSource = string.Concat(DataSource, FormIniz.cartellaSimb, ";");
            SQLiteConnection conn = new SQLiteConnection(DataSource);
            return (conn);
        }

        public struct Find
        {
            public Point P1;
            public Point P2;
            public Point P3;
            public Point P4;
            public string IDtavol;
            public string codice;
        }

        public static Find[] ivect;

        private int findNrec;

        private int readFileQU5000()
        {

            using (SQLiteConnection conn = SetConnection1())
            {
                conn.Open();
                using (SQLiteCommand cmd = new SQLiteCommand(conn))
                {
                    string ss1 = "select count(*) from QU_5000";

                    cmd.CommandText = ss1;
                    // tables:  QU_5000   QU_10000  QU_25000
                    //  campi:  codice nome  X1  Y1  X2  Y2  X3  Y3  X4  Y4

                    int nrec = 0;
                    SQLiteDataReader reader1 = cmd.ExecuteReader();
                    if (reader1.HasRows)
                    {
                        while (reader1.Read())
                        {
                            nrec = reader1.GetInt32(0);
                        }
                    }
                    if (nrec == 0)
                    {
                        MessageBox.Show("non trovato alcun elemento");
                        return 1;
                    }
                    reader1.Close();

                    ivect = new Find[nrec];
                    findNrec = nrec;

                    ss1 = "select * from QU_5000";

                    cmd.CommandText = ss1;
                    SQLiteDataReader reader = cmd.ExecuteReader();
                    if (reader.HasRows)
                    {
                        int i = 0;
                        while (reader.Read())
                        {
                            ivect[i].codice = reader.GetString(0).ToString();
                            ivect[i].IDtavol = reader.GetString(1).ToString();
                            if (i == 0)
                            {
                                // dim. min-max
                                int Xmin = int.Parse(reader.GetString(4).ToString());
                                int Ymin = int.Parse(reader.GetString(3).ToString());
                                int Xmax = int.Parse(reader.GetString(8).ToString());
                                int Ymax = int.Parse(reader.GetString(7).ToString());

                                ivect[0].P1.X = Xmin;
                                ivect[0].P1.Y = Ymin;
                                ivect[0].P2.X = Xmax;
                                ivect[0].P2.Y = Ymax;

                                int XXmin = Xmin;
                                int YYmin = Ymin;
                                int XXmax = Xmax;
                                int YYmax = Ymax;



                            }
                            else
                            {
                                ivect[i].P1.X = int.Parse(reader.GetString(2).ToString());
                                ivect[i].P1.Y = int.Parse(reader.GetString(3).ToString());
                                ivect[i].P2.X = int.Parse(reader.GetString(4).ToString());
                                ivect[i].P2.Y = int.Parse(reader.GetString(5).ToString());
                                ivect[i].P3.X = int.Parse(reader.GetString(6).ToString());
                                ivect[i].P3.Y = int.Parse(reader.GetString(7).ToString());
                                ivect[i].P4.X = int.Parse(reader.GetString(8).ToString());
                                ivect[i].P4.Y = int.Parse(reader.GetString(9).ToString());
                            }
                            ++i;
                        }
                    }

                }
                conn.Close();
            }

            return 0;
        }



        private int index;
        private string codex;

        private int findFirstElement(int utmX, int utmY)
        {

            int ifound, isign, i, nrec;
            long A, B, C, D;

            nrec = findNrec;

            ifound = 0;
            for (i = 1; i <= nrec; ++i)
            {
                A = ivect[i].P2.Y - ivect[i].P1.Y;
                B = ivect[i].P1.X - ivect[i].P2.X;
                C = ((long)ivect[i].P2.X) * ((long)ivect[i].P1.Y) - ((long)ivect[i].P1.X) * ((long)ivect[i].P2.Y);
                D = A * utmX + B * utmY + C;
                isign = 1;
                if (D < 0) isign = -1;

                A = ivect[i].P3.Y - ivect[i].P2.Y;
                B = ivect[i].P2.X - ivect[i].P3.X;
                C = ((long)ivect[i].P3.X) * ((long)ivect[i].P2.Y) - ((long)ivect[i].P2.X) * ((long)ivect[i].P3.Y);
                D = A * utmX + B * utmY + C;
                if (isign == 1 & D < 0) goto L90;
                if (isign == -1 & D > 0) goto L90;

                A = ivect[i].P4.Y - ivect[i].P3.Y;
                B = ivect[i].P3.X - ivect[i].P4.X;
                C = ((long)ivect[i].P4.X) * ((long)ivect[i].P3.Y) - ((long)ivect[i].P3.X) * ((long)ivect[i].P4.Y);
                D = A * utmX + B * utmY + C;
                if (isign == 1 & D < 0) goto L90;
                if (isign == -1 & D > 0) goto L90;

                A = ivect[i].P1.Y - ivect[i].P4.Y;
                B = ivect[i].P4.X - ivect[i].P1.X;
                C = ((long)ivect[i].P1.X) * ((long)ivect[i].P4.Y) - ((long)ivect[i].P4.X) * ((long)ivect[i].P1.Y);
                D = A * utmX + B * utmY + C;
                if (isign == 1 & D < 0) goto L90;
                if (isign == -1 & D > 0) goto L90;

                ifound = 1;
                break;
            L90: continue;
            }
            if (ifound == 0)
            {
                MessageBox.Show("non trovato");
                return -1;
            }
            else
            {
                string s1 = ivect[i].IDtavol.Trim();
                codex = ivect[i].codice.Trim();
                index = i;
                //               MessageBox.Show(" trovato  :"+ s2);
                return 0;


            }
        }

        int pointInTheElement(int utmX, int utmY)
        {

            int ifound = 0;
            int isign;
            int i = index;
            long A, B, C, D;

            A = ivect[i].P2.Y - ivect[i].P1.Y;
            B = ivect[i].P1.X - ivect[i].P2.X;
            C = ((long)ivect[i].P2.X) * ((long)ivect[i].P1.Y) - ((long)ivect[i].P1.X) * ((long)ivect[i].P2.Y);
            D = A * utmX + B * utmY + C;
            isign = 1;
            if (D < 0) isign = -1;

            A = ivect[i].P3.Y - ivect[i].P2.Y;
            B = ivect[i].P2.X - ivect[i].P3.X;
            C = ((long)ivect[i].P3.X) * ((long)ivect[i].P2.Y) - ((long)ivect[i].P2.X) * ((long)ivect[i].P3.Y);
            D = A * utmX + B * utmY + C;
            if (isign == 1 & D < 0) goto L90;
            if (isign == -1 & D > 0) goto L90;

            A = ivect[i].P4.Y - ivect[i].P3.Y;
            B = ivect[i].P3.X - ivect[i].P4.X;
            C = ((long)ivect[i].P4.X) * ((long)ivect[i].P3.Y) - ((long)ivect[i].P3.X) * ((long)ivect[i].P4.Y);
            D = A * utmX + B * utmY + C;
            if (isign == 1 & D < 0) goto L90;
            if (isign == -1 & D > 0) goto L90;

            A = ivect[i].P1.Y - ivect[i].P4.Y;
            B = ivect[i].P4.X - ivect[i].P1.X;
            C = ((long)ivect[i].P1.X) * ((long)ivect[i].P4.Y) - ((long)ivect[i].P4.X) * ((long)ivect[i].P1.Y);
            D = A * utmX + B * utmY + C;
            if (isign == 1 & D < 0) goto L90;
            if (isign == -1 & D > 0) goto L90;

            ifound = 1;
        L90: return (ifound);
        }
 
        private static SQLiteConnection SetConnection1()
        {
            string DataSource = "Data Source=";
            DataSource = string.Concat(DataSource, FormIniz.quadroUnione, ";");
            SQLiteConnection conn = new SQLiteConnection(DataSource);
            return (conn);
        }   


        private void button1_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.No;
            this.Close();
        }

        int convertFile(string path, string path1)
        {
            if (!File.Exists(path))
            {
                MessageBox.Show("non esiste il file " + path);
                return 1;
            }

            if (File.Exists(path1)) File.Delete(path1);


            StreamReader sf1 = File.OpenText(path);
            StreamWriter sw1 = new StreamWriter(path1);
            while (!sf1.EndOfStream)
            {
                string s1 = sf1.ReadLine();
                int len = s1.Length;
                if (len > 0)
                {
                    string s2 = s1.Substring(0, 1);
                    string s3 = string.Empty;
                    if (s2.Equals("-"))
                    {
                        s3 = s1.Substring(1, len - 1);
                    }
                    else s3 = s1;
                    sw1.WriteLine(s3);
                }
            }

            sf1.Close();

            sw1.Close();
            return 2;
        }

      
        private void button2_Click(object sender, EventArgs e)
        {
            string input = textBox1.Text;
            string path = FormIniz.cartellaGPS;
            string file_r = string.Concat(path, input);


        }

  
    }
}
